package top.itaso.lib.widget;

import android.annotation.SuppressLint;
import android.content.Context;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import java.util.ArrayList;
import java.util.List;

/**
 * @Description: 模糊过滤输入内容，类似 AutoCompleteTextView 的下拉联想搜索输入内容
 * @Author itsdf07
 * @E-Mail 923255742@qq.com
 * @Gitee https://gitee.com/itsdf07
 * @Date 2022/9/24
 */
public class AutoFilterInputEditView extends androidx.appcompat.widget.AppCompatEditText {
    private final String TAG = this.getClass().getSimpleName();
    private ArrayList<Node> allNodes = new ArrayList<>();
    private ArrayList<Node> findNodes = new ArrayList<>();
    private PopupWindow filterPopup;
    private RecyclerView filterListView;
    private FilterAdapter adapter;

    private MutableLiveData<Node> _resultNode = new MutableLiveData<>();
    private LiveData<Node> resultNode = _resultNode;

    public AutoFilterInputEditView(@NonNull Context context) {
        this(context, null);
    }

    public AutoFilterInputEditView(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);

        addTextChangedListener(inputChanged);

        setBackground(getResources().getDrawable(R.drawable.shape_bg_normal));

        filterListView = new RecyclerView(getContext());
        filterListView.setBackground(getResources().getDrawable(R.drawable.selector_bg_rectangular));
        filterListView.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false));
        adapter = new FilterAdapter();
        filterListView.setAdapter(adapter);
        setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                showFilterInputWindow(v);
            }
        });
        setOnFocusChangeListener(new OnFocusChangeListener() {
            @Override
            public void onFocusChange(View v, boolean hasFocus) {
                if (hasFocus) {
                    showFilterInputWindow(v);
                }
            }
        });
    }

    /**
     * 设置过滤数据，初始时，结果集合=全数据集合
     *
     * @param newNodes
     */
    public void updateNodes(ArrayList<Node> newNodes) {
        if (newNodes == null) {
            return;
        }
//        if (!newNodes.isEmpty()) {
//            Node childNode = newNodes.get(0);
//            setText(childNode.getTitle());
//        }
        setText("");
        Log.d(TAG, "updateNodes: >>>>>>newNodes.size=" + newNodes.size());
        allNodes.clear();
        allNodes.addAll(newNodes);
        findNodes.clear();
        findNodes.addAll(newNodes);

    }

    public LiveData<Node> getResultNode() {
        return resultNode;
    }

    /**
     * 从 allNodes 中过滤出关键值，结果集合存入 findNodes
     *
     * @param keyValue
     */
    private void filterFromAllNodes(String keyValue) {
        if (keyValue == null) {
            return;
        }
        findNodes.clear();
        for (Node node : allNodes) {
            if (node.title.contains(keyValue)) {
                findNodes.add(node);
            }
        }
        Log.d(TAG, "filterFromAllNodes: >>>>>>findNodes.size=" + findNodes.size());
    }

    /**
     * 从 findNodes 中过滤出关键值，并更新到 findNodes
     *
     * @param keyValue
     */
    private void filterFromFindNodes(String keyValue) {
        if (keyValue == null) {
            return;
        }
        ArrayList<Node> temp = new ArrayList<>();

        for (Node node : findNodes) {
            if (node.title.contains(keyValue)) {
                temp.add(node);
            }
        }
        findNodes.clear();
        findNodes.addAll(temp);
        Log.d(TAG, "filterFromFindNodes: >>>>>> findNodes.size=" + findNodes.size());
    }

    private TextWatcher inputChanged = new TextWatcher() {
        private String beforeText = "";

        @Override
        public void beforeTextChanged(CharSequence beforeChangeText, int start, int count, int after) {
            Log.v(TAG, "beforeTextChanged: >>>>>>start:" + start + ",after" + after + ",count:" + count + ",beforeChangeText:" + beforeChangeText);
            beforeText = beforeChangeText.toString();
        }

        @Override
        public void onTextChanged(CharSequence changeText, int start, int before, int count) {
            Log.v(TAG, "beforeTextChanged: >>>>>>start:" + start + ",before" + before + ",count:" + count + ",changeText:" + changeText);
        }

        @Override
        public void afterTextChanged(Editable resultText) {
            String afterChangeText = resultText.toString();
            Log.v(TAG, "afterTextChanged: >>>>>>afterChangeText=" + afterChangeText);
            if (afterChangeText.length() > beforeText.length()) {//输入，从已筛选结果中继续筛选
                filterFromFindNodes(afterChangeText);
            } else if (afterChangeText.length() < beforeText.length()) {//删除，，从所有数据从新筛选
                filterFromAllNodes(afterChangeText);
            } else {

            }
            adapter.notifyDataSetChanged();
        }
    };


    /**
     * 根据分辨率从 dp 的单位 转成为 px(像素)
     */
    public int dp2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

    /**
     * 过滤应用列表分类的交互窗口-Popupwindow 实现
     *
     * @param anchor
     */
    private void showFilterInputWindow(View anchor) {
        if (filterPopup == null) {
            filterPopup = new PopupWindow();
            filterPopup.setFocusable(false);
            filterListView.setFocusable(false);
            filterPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
            filterPopup.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
            filterPopup.setContentView(filterListView);//设置要弹出的界面
            filterPopup.setWidth(getWidth());//设置弹出框的尺寸为适应控件

//            filterPopup.setHeight(200);
            filterPopup.setHeight(DrawerLayout.LayoutParams.WRAP_CONTENT);
            filterPopup.setOutsideTouchable(true);

//        filterPopup.setBackgroundDrawable(getContext().getDrawable(R.drawable.shape_bg_item_normal));
            filterPopup.setOnDismissListener(new PopupWindow.OnDismissListener() {
                @Override
                public void onDismiss() {
                    Log.d(TAG, "onDismiss: >>>>>>filterPopup is dismiss");
                }
            });
        }
        if (!filterPopup.isShowing()) {
            filterPopup.showAsDropDown(anchor);
        }
        adapter.notifyDataSetChanged();
    }


    private class FilterAdapter extends RecyclerView.Adapter<FilterAdapter.FilterViewHolder> {
        private int createViewposition = 0;

        public FilterAdapter() {
            this.createViewposition = 0;
        }

        @Override
        public FilterViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            TextView filterItem = new TextView(parent.getContext());
            filterItem.setBackground(getResources().getDrawable(R.drawable.selector_bg_rectangular));
            filterItem.setTextSize(TypedValue.COMPLEX_UNIT_SP, 12);
            filterItem.setPadding(dp2px(getContext(), 5),
                    0,
                    0,
                    0);
            filterItem.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);

            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
            int margin = dp2px(getContext(), 3);
            params.setMargins(margin, margin, margin, (createViewposition < findNodes.size() - 1) ? 0 : margin);//动态设置Item的外边距，为了每个Item的间距相同，故除最后一个之外，其他都只设置左上右
            params.height = dp2px(getContext(), 34);
            filterItem.setLayoutParams(params);
            createViewposition++;
            return new FilterViewHolder(filterItem);
        }

        @Override
        public void onBindViewHolder(@NonNull FilterViewHolder viewHolder, @SuppressLint("RecyclerView") int position) {
            Node filterContentItem = findNodes.get(position);
            viewHolder.name.setText(filterContentItem.getTitle());
            viewHolder.itemView.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (filterPopup != null) {
                        filterPopup.dismiss();
                    }
                    setText(filterContentItem.getTitle());
                    setSelection(getText().length());
                    _resultNode.setValue(filterContentItem);
                }
            });
        }

        @Override
        public int getItemCount() {
            return findNodes.size();
        }

        class FilterViewHolder extends RecyclerView.ViewHolder {
            private TextView name;

            public FilterViewHolder(View itemView) {
                super(itemView);
                name = (TextView) itemView;
            }
        }

    }

    /**
     * 节点实例
     *
     * @param <T>
     */
    public static class Node<T> {
        /**
         * 当前节点id
         */
        private String id;

        /**
         * 父节点id
         */
        private String pid;

        /**
         * 节点数据实体类
         */
        private T data;

        /**
         * 下一级的子Node
         */
        private List<Node> children = new ArrayList<>();


        /**
         * 节点名称
         */
        private String title;

        /**
         * 当前的级别
         */
        private int level;

        /**
         * 父Node
         */
        private Node parentNode;


        public Node(String id, String pid, int level, String title) {
            this.id = id;
            this.pid = pid;
            this.title = title;
            this.level = level;
        }

        public Node(String id, String pid, int level, String title, T data) {
            this.id = id;
            this.pid = pid;
            this.title = title;
            this.level = level;
            this.data = data;
        }

        /**
         * @return 当前是否为根节点
         */
        public boolean isRootNode() {
            return parentNode == null;
        }


        /**
         * @return 当前是否叶子节点，即最后一级
         */
        public boolean isLeaf() {
            return children == null || children.isEmpty();
        }

        /**
         * @return 获取当前节点的级别
         */
        public int getTreeLevel() {
            return parentNode == null ? 0 : parentNode.getTreeLevel() + 1;
        }

        public String getId() {
            return id;
        }

        public void setId(String id) {
            this.id = id;
        }

        public String getPid() {
            return pid;
        }

        public void setPid(String pid) {
            this.pid = pid;
        }

        public T getData() {
            return data;
        }

        public void setData(T data) {
            this.data = data;
        }

        public List<Node> getChildren() {
            return children;
        }

        public void setChildren(List<Node> children) {
            this.children = children;
        }

        public String getTitle() {
            return title;
        }

        public void setTitle(String title) {
            this.title = title;
        }

        public int getLevel() {
            return level;
        }

        public void setLevel(int level) {
            this.level = level;
        }

        public Node getParentNode() {
            return parentNode;
        }

        public void setParentNode(Node parentNode) {
            this.parentNode = parentNode;
        }

        public static class NodeData {

            private String name;

            public NodeData() {
            }

            public NodeData(String name) {
                this.name = name;
            }

            public String getName() {
                return name;
            }

            public void setName(String name) {
                this.name = name;
            }
        }
    }
}
